package com.artisan.springuitls.demos;

import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * ReflectionUtils 工具类演示
 * 功能：反射操作安全网
 * 优势：自动处理 setAccessible(true)，避免手写 try-catch
 * 
 * ⚠️ 提醒：仅推荐在测试中使用，生产代码避免反射
 */
@Component
public class ReflectionUtilsDemo {

    /**
     * 场景：测试中调用私有方法
     */
    public void testPrivateMethod() {
        System.out.println("\n========== ReflectionUtils Demo ==========");
        
        UserService userService = new UserService();
        
        // ✅ 自动查找私有方法
        Method method = ReflectionUtils.findMethod(
            UserService.class, "sendWelcomeEmail", Long.class
        );
        
        if (method != null) {
            // ✅ 自动设 accessible + 调用
            ReflectionUtils.invokeMethod(method, userService, 1001L);
        }
    }

    /**
     * 演示字段操作
     */
    public void demonstrateFieldOperations() {
        System.out.println("\n--- 字段反射操作 ---");
        
        User user = new User("张三", 25);
        
        // 1. 查找字段
        Field nameField = ReflectionUtils.findField(User.class, "name");
        System.out.println("✓ 找到字段: " + (nameField != null ? nameField.getName() : "null"));
        
        // 2. 设置字段可访问并获取值
        if (nameField != null) {
            ReflectionUtils.makeAccessible(nameField);
            Object value = ReflectionUtils.getField(nameField, user);
            System.out.println("✓ name 字段值: " + value);
            
            // 3. 设置字段值
            ReflectionUtils.setField(nameField, user, "李四");
            System.out.println("✓ 修改后 name: " + user.getName());
        }
        
        // 4. 遍历所有字段
        System.out.println("✓ 所有字段:");
        ReflectionUtils.doWithFields(User.class, field -> {
            System.out.println("  - " + field.getName() + ": " + field.getType().getSimpleName());
        });
        
        // 5. 遍历特定类型字段（只处理 String 类型）
        System.out.println("✓ String 类型字段:");
        ReflectionUtils.doWithFields(User.class, 
            field -> System.out.println("  - " + field.getName()),
            field -> field.getType().equals(String.class));
        
        System.out.println();
    }

    /**
     * 演示方法操作
     */
    public void demonstrateMethodOperations() {
        System.out.println("\n--- 方法反射操作 ---");
        
        UserService service = new UserService();
        
        // 1. 查找公共方法
        Method publicMethod = ReflectionUtils.findMethod(
            UserService.class, "publicMethod", String.class);
        if (publicMethod != null) {
            Object result = ReflectionUtils.invokeMethod(publicMethod, service, "测试");
            System.out.println("✓ 公共方法返回: " + result);
        }
        
        // 2. 遍历所有方法
        System.out.println("✓ 所有声明的方法:");
        ReflectionUtils.doWithMethods(UserService.class, method -> {
            System.out.println("  - " + method.getName() + "()");
        });
        
        // 3. 遍历特定方法（只处理无参方法）
        System.out.println("✓ 无参方法:");
        ReflectionUtils.doWithMethods(UserService.class,
            method -> System.out.println("  - " + method.getName()),
            method -> method.getParameterCount() == 0);
        
        System.out.println();
    }

    /**
     * 演示工具方法
     */
    public void demonstrateUtilityMethods() {
        System.out.println("\n--- 反射工具方法 ---");
        
        // 1. 判断是否为 equals 方法
        Method equalsMethod = ReflectionUtils.findMethod(Object.class, "equals", Object.class);
        System.out.println("✓ 是否为 equals 方法: " + ReflectionUtils.isEqualsMethod(equalsMethod));
        
        // 2. 判断是否为 hashCode 方法
        Method hashCodeMethod = ReflectionUtils.findMethod(Object.class, "hashCode");
        System.out.println("✓ 是否为 hashCode 方法: " + ReflectionUtils.isHashCodeMethod(hashCodeMethod));
        
        // 3. 判断是否为 toString 方法
        Method toStringMethod = ReflectionUtils.findMethod(Object.class, "toString");
        System.out.println("✓ 是否为 toString 方法: " + ReflectionUtils.isToStringMethod(toStringMethod));
        
        // 4. 判断是否为 Object 类声明的方法
        System.out.println("✓ equals 是否为 Object 方法: " + 
            ReflectionUtils.isObjectMethod(equalsMethod));
        
        // 5. 获取所有已声明的方法（包括私有）
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(UserService.class);
        System.out.println("✓ 总方法数: " + methods.length);
        
        // 6. 获取唯一已声明的方法
        Method uniqueMethod = ReflectionUtils.getUniqueDeclaredMethods(UserService.class)[0];
        System.out.println("✓ 第一个唯一方法: " + uniqueMethod.getName());
        
        System.out.println("==========================================\n");
    }

    /**
     * 模拟 UserService
     */
    static class UserService {
        private void sendWelcomeEmail(Long userId) {
            System.out.println("✓ 发送欢迎邮件给用户: " + userId);
        }

        public String publicMethod(String param) {
            return "处理参数: " + param;
        }

        public void noArgMethod() {
            System.out.println("无参方法");
        }
    }

    /**
     * 模拟 User 对象
     */
    static class User {
        private String name;
        private Integer age;

        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }
    }
}

